//Type utilities
//$Id: type_util.h 395 2010-03-26 14:01:03Z Oleg.Bulychov $
#pragma once

#include <functional>
#include <typeinfo>
#include "compiler_defines.h"
//__________________________________________________________________________________
namespace meta
{
//__________________________________________________________________________________
template<typename T>
struct is_class
{
private:
    struct true_t { char dummy[1]; };
    struct false_t { char dummy[2]; };
    template< typename C > static true_t test(int C::*);
    template< typename C > static false_t test(...);
public:

    enum { result = (sizeof(test<T>(0)) == sizeof(true_t)) };
};
//_______________________________________________________________________________
template<>
struct is_class<void>
{
    enum { result = false };
};
//__________________________________________________________________________________
//__________________________________________________________________________________
template<typename T, bool = !is_class<T>::result>
struct is_polymorphic_helper
{ 
private:
    template<typename U>
    struct first: public U
    {};
    template<typename U>
    struct second: public U
    { 
        virtual void dummy();
        virtual ~second() throw();
    };

public:
    static const bool value = sizeof(first<T>) == sizeof(second<T>);
};

template<typename T>
struct is_polymorphic_helper<T, true>
{ static const bool value = false; };

template<typename T>
struct is_polymorphic
{
    enum { result = is_polymorphic_helper<T>::value ? 1 : 0 };
};
//__________________________________________________________________________________
//__________________________________________________________________________________
template<int i>
struct int2type
{
    enum { result = i };
};
//__________________________________________________________________________________
template<typename T>
struct type2type
{
    typedef T result;
};
//__________________________________________________________________________________
template<bool flag, typename T, typename U>
struct bool2type
{
    typedef T result;
};
template<typename T, typename U>
struct bool2type<false, T, U>
{
    typedef U result;
};
//__________________________________________________________________________________
template<typename T>
struct is_array
{
    enum {result = 0};
};
template<typename T, size_t N>
struct is_array<T[N]>
{
    enum
    {
        result = 1,
        array_size = N
    };
};
template<typename T>
struct is_array<T[]>
{
    enum
    {
        result = 1,
        array_size = 0
    };
};
//__________________________________________________________________________________
template<typename T>
struct is_pointer
{
    enum {result = 0};
};
template<typename T>
struct is_pointer<T*>
{
    enum {result = 1};
};
//__________________________________________________________________________________
/*
template<typename T>
inline int Is_Pointer(T& t)
{
    return is_pointer<T>::result;
}
template<typename T>
inline int Is_Array(T& t)
{
    return is_array<T>::result;
}
*/
//__________________________________________________________________________________
template<typename T, typename U>
struct is_same_type
{
    enum { result = 0 };
};
template<typename T>
struct is_same_type<T, T>
{
    enum { result = 1 };
};
//__________________________________________________________________________________
struct type_info_less:
    public std::binary_function<std::type_info const*, std::type_info const*, bool>
{
    bool operator()(std::type_info const* left, std::type_info const* right) const
    {
        return left->before(*right) != 0;
    }
};
//_______________________________________________________________________________
template<typename T>
struct is_integral_type
{
    enum {result = 0};
};
//__________________________________________________________________________________
template<> struct is_integral_type<bool>
{ enum {result = 1}; };
template<> struct is_integral_type<char>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned char>
{ enum {result = 1}; };
template<> struct is_integral_type<short>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned short>
{ enum {result = 1}; };
template<> struct is_integral_type<int>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned int>
{ enum {result = 1}; };
template<> struct is_integral_type<long>
{ enum {result = 1}; };
template<> struct is_integral_type<unsigned long>
{ enum {result = 1}; };
template<> struct is_integral_type<float>
{ enum {result = 1}; };
template<> struct is_integral_type<double>
{ enum {result = 1}; };

//:LLP64 vs LP64
#if (!INT64_EQUAL_LONG)
template<> struct is_integral_type<int64_t>
{ enum {result = 1}; };
template<> struct is_integral_type<uint64_t>
{ enum {result = 1}; };
#endif
//__________________________________________________________________________________
//__________________________________________________________________________________
template <void(*)()>
struct instantiate_function
{};
//__________________________________________________________________________________
//__________________________________________________________________________________
}//meta

//EOF!
